#include "math/AFilter.h"
#include "math/float2int.h"
#include "xtd/Arr2D.h"
#include "cinline.h"

#pragma warning(disable: 4244)

AFilter::AFilter() : m_smooth(NULL), m_differ(NULL), m_double(NULL)
{
  Clear();
}


AFilter::~AFilter()
{
  Clear();
}


void AFilter::Clear()
{
  m_smooth = YATL::FreeArray2D<float>(m_smooth);
  m_differ = YATL::FreeArray2D<float>(m_differ);
  m_double = YATL::FreeArray2D<float>(m_double);
  m_nFilter = m_size = 0;
  m_param = m_dParam = 0.0;
}


//--------------------------------------------------------------------------
// Function creates filters with specified parameters. If parameters
// coincide with currently used ones, then function does nothing.
//--------------------------------------------------------------------------
void AFilter::Create(
  int    nFilter,       // number of filters to be created (always odd!)
  double param,         // smoothing parameter
  double fraction)      // delta(param) = fraction * param
{
  assert(nFilter > 0 && (nFilter & 1) != 0);
  param = ValidateParameter(param);
  fraction = limit(fraction, 0.001, 0.1);
  assert( "Too many filters" && !(nFilter > round(0.25/fraction)) );

  if (nFilter == m_nFilter && fabs(param - m_param) < FLT_EPSILON &&
      fabs(fraction*param - m_dParam) < FLT_EPSILON)
    return;

  Clear();
  int half = nFilter/2;
  m_param = param;
  m_dParam = fraction*param;
  m_nFilter = nFilter;
  m_size = GetFilterLength(nFilter, param, m_dParam);
  m_smooth = YATL::AllocArray2D<float>(nFilter, m_size, 0.0f, true);
  m_differ = YATL::AllocArray2D<float>(nFilter, m_size, 0.0f, true);
  m_double = YATL::AllocArray2D<float>(nFilter, m_size, 0.0f, true);

  ComputeFilter(m_smooth[half], m_differ[half], m_double[half], param);
  for(int k = 1; k <= half; k++)
  {
    ComputeFilter(m_smooth[half-k], m_differ[half-k], m_differ[half-k], param-k*m_dParam);
    ComputeFilter(m_smooth[half+k], m_differ[half+k], m_differ[half+k], param+k*m_dParam);
  }
}
